package com.stars.services.impl;

import com.stars.common.MyDateUtils;
import com.stars.common.base.BaseUUID;
import com.stars.common.base.ResultMsg;
import com.stars.common.chart.*;
import com.stars.common.enums.AutoCodeTypeEnum;
import com.stars.common.maps.MyMapUtils;
import com.stars.common.valid.MyException;
import com.stars.dao.mapper.echarts.MyChartsMapper;
import com.stars.services.BaseAccessService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import tk.mybatis.mapper.common.Mapper;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * Created by luodajie on 2019/1/5.
 */
public class BaseAccessServiceImpl<M extends Mapper<T>, T> implements BaseAccessService<T> {

    @Autowired
    protected M mapper;
    @Autowired
    protected MyChartsMapper myChartsMapper;

    public void setMapper(M mapper) {
        this.mapper = mapper;
    }

    @Override
    public T selectOne(T entity) {
        return mapper.selectOne(entity);
    }

    @Override
    public T selectById(Object id) {
        return mapper.selectByPrimaryKey(id);
    }

    @Override
    public List<T> selectList(T entity) {
        return mapper.select(entity);
    }

    @Override
    public List<T> selectListAll() {
        return mapper.selectAll();
    }

    @Override
    public Long selectCount(T entity) {
        return new Long(mapper.selectCount(entity));
    }

    @Override
    public List<T> selectByExample(Object example) {
        return mapper.selectByExample(example);
    }

    @Override
    public int selectCountByExample(Object example) {
        return mapper.selectCountByExample(example);
    }

    @Override
    public ResultMsg countByTableColumns(String tableName, String columnsName, String whereColumns, String chartType) {
        checkCountAndSum(tableName, columnsName);
        List<Map<String, Object>> mapList = myChartsMapper.countColumnsByTable(tableName, columnsName, whereColumns);
        if (null != mapList) {
            final Map<String, BigDecimal> maps = MyMapUtils.listMapToMap(mapList);
            if (ChartTypeEnum.PIE.getValue().equals(chartType)) {
                PieChart pieChart = new PieChart("计数", "计数", MyMapUtils.mapKeyToArray(maps), MyMapUtils.pieValueName(maps));
                return ResultMsg.success(pieChart);
            } else {
                List<SeriesData> seriesDataList = new LinkedList<>();
                SeriesData seriesData = new SeriesData();
                seriesData.setData(MyMapUtils.valueToArray(maps));
                seriesDataList.add(seriesData);
                LineBarChart lineBarChart = new LineBarChart("计数", "计数", MyMapUtils.nameToArray(maps), seriesDataList, chartType);
                return ResultMsg.success(lineBarChart);
            }
        }
        return ResultMsg.success();

    }

    @Override
    public ResultMsg sumByTableColumns(String tableName, String columnsName, Map<String, String> colMap, String whereColumns, String chartType) {
        checkCountAndSum(tableName, columnsName);
        if (null == colMap) {
            throw new MyException("求和列名不能为空");
        }
        List<String> legendDataList = new LinkedList<>();
        List<PieSeriesData> seriesMapDataList = new LinkedList<>();
        List<SeriesData> seriesDataList = new LinkedList<>();
        List<String> xAxisData = new LinkedList<>();
        colMap.forEach((k, v) -> {
            List<Map<String, Object>> mapList = myChartsMapper.sumColumnsByTable(tableName, columnsName, k, whereColumns);
            if (null != mapList) {
                Map<String, BigDecimal> maps = MyMapUtils.listMapToMap(mapList);
                legendDataList.add(v);
                seriesMapDataList.addAll(MyMapUtils.pieValueName(maps));
                SeriesData seriesData1 = new SeriesData();
                seriesData1.setName("");
                seriesData1.setData(MyMapUtils.valueToArray(maps));
                seriesDataList.add(seriesData1);
                xAxisData.addAll(MyMapUtils.nameToArray(maps));
            }
        });
        List<String> newXAxisData = xAxisData.stream().distinct().collect(Collectors.toList());
        if (ChartTypeEnum.PIE.getValue().equals(chartType)) {
            PieChart pieChart = new PieChart("求和", "求和", legendDataList, seriesMapDataList);
            return ResultMsg.success(pieChart);
        } else {
            LineBarChart lineBarChart = new LineBarChart("求和", "求和", newXAxisData, legendDataList, seriesDataList, chartType);
            return ResultMsg.success(lineBarChart);
        }
    }

    @Override
    public List<DataDTO> charCount(String tableName, Map<String,String> columnsNameMap, String whereColumns) {
        checkCountAndSum(tableName);
        List<DataDTO> list = new LinkedList<>();
        if(null != columnsNameMap){
            columnsNameMap.forEach((k,v)->{
                List<Map<String, Object>> mapList = myChartsMapper.countColumnsByTable(tableName, k, whereColumns);
                if (null != mapList) {
                    Map<String, BigDecimal> stringBigDecimalMap = MyMapUtils.listMapToMap(mapList);
                    List<DataDTO> listData =  MyMapUtils.mapToValueName(stringBigDecimalMap);
                    list.addAll(listData);
                }
            });
        }else {
            List<Map<String, Object>> maps = myChartsMapper.countColumnsByTable(tableName, null, whereColumns);
            BigDecimal bigDecimal = MyMapUtils.mapListToBigDecimal(maps);
            DataDTO pieSeriesData = new DataDTO();
            pieSeriesData.setId(BaseUUID.getUUID());
            pieSeriesData.setValue(bigDecimal);
            list.add(pieSeriesData);
        }

        return list;

    }

    @Override
    public List<DataDTO>  charSum(String tableName, String columnsName, Map<String, String> colMap, String whereColumns) {
        checkCountAndSum(tableName);

        List<DataDTO> listBigDecimal = new LinkedList<>();
        colMap.forEach((k, v) -> {
            List<Map<String, Object>> mapList = myChartsMapper.sumColumnsByTable(tableName, columnsName, k, whereColumns);
            if (null != mapList) {
                //没有分组求和
                if(StringUtils.isBlank(columnsName)){
                    BigDecimal bigDecimal = MyMapUtils.mapListToBigDecimal(mapList);
                    DataDTO pieSeriesData = new DataDTO();
                    pieSeriesData.setId(k);
                    pieSeriesData.setName(v);
                    pieSeriesData.setValue(bigDecimal);
                    listBigDecimal.add(pieSeriesData);
                }else {
                    Map<String, BigDecimal> stringBigDecimalMap = MyMapUtils.listMapToMap(mapList);
                    List<DataDTO> listData =  MyMapUtils.mapToValueName(stringBigDecimalMap);
                    listBigDecimal.addAll(listData);
                }
            }
        });
        return listBigDecimal;
    }

    @Override
    public Map<String, Object> findDictTableToMap(String tableName, String dictCode, String columnsName) throws Exception {
        checkCountAndSum(tableName, columnsName);
        if (StringUtils.isBlank(dictCode)) {
            dictCode = "id";
        }
        List<Map<String, Object>> mapList = myChartsMapper.findDictByTable(tableName, dictCode, columnsName);
        return MyMapUtils.listMapDictToMap(mapList);
    }

    @Override
    public Integer fieldRepeatVail(String tableName, Map<String, String> map) throws Exception {
        if (null == map) {
            return 0;
        }
        if (StringUtils.isBlank(tableName)) {
            return 0;
        }
        StringBuilder params = new StringBuilder();
        map.forEach((key, val) -> {
            if ("id".equals(key)) {
                params.append("   AND " + key + "!='" + val + "'");
            } else {
                params.append("   AND " + key + "='" + val + "'");
            }
        });
        return myChartsMapper.checkFieldRepeat(tableName, params.toString());
    }

    @Override
    public String createCode(String tableName, String columnsName, String prefix, AutoCodeTypeEnum typeEnum, String dbWhereStr, String dbWhereVal) throws Exception {
        List<Map<String, Object>> maxCodeList = myChartsMapper.getMaxCode(tableName, columnsName, dbWhereStr, dbWhereVal);
        //数据最大的流水号
        String maxCode = "";
        if (maxCodeList.size() > 0 && null != maxCodeList.get(0)) {
            Object obj = maxCodeList.get(0).get("maxCode");
            if (null != obj) {
                maxCode = obj.toString();
            }
        }
        return AutoCodeTypeEnum.MONTH.equals(typeEnum) ? genCodeByMonth(maxCode, prefix) : genCode(maxCode, prefix);
    }

    /**
     * 每天四位流水号
     *
     * @param maxCode
     * @param prefix
     * @return
     */
    private String genCode(String maxCode, String prefix) {
        String dateStr = MyDateUtils.format(new Date(), MyDateUtils.YYYY_MM_DD);
        //定义拼接好的流水
        String commentCode = "";
        if (StringUtils.isNotBlank(maxCode) && maxCode.contains(dateStr)) {
            String uidEnd = maxCode.substring(prefix.length() + dateStr.length(), maxCode.length());
            Integer endNum = Integer.parseInt(uidEnd);
            String temp = 10000 + endNum + 1 + "";
            commentCode = prefix + dateStr + temp.substring(1);
        } else {
            commentCode = prefix + dateStr + "0001";
        }
        return commentCode;
    }

    /**
     * 每月份生成三位流水号
     *
     * @param maxCode
     * @param prefix
     * @return
     */
    private String genCodeByMonth(String maxCode, String prefix) {
        String dateStr = MyDateUtils.format(new Date(), MyDateUtils.YYYY_MM);
        //定义拼接好的流水
        String commentCode = "";
        if (StringUtils.isNotBlank(maxCode) && maxCode.contains(dateStr)) {
            String uidEnd = maxCode.substring(prefix.length() + dateStr.length(), maxCode.length());
            Integer endNum = Integer.parseInt(uidEnd);
            String temp = 1000 + endNum + 1 + "";
            commentCode = prefix + dateStr + temp.substring(1);
        } else {
            commentCode = prefix + dateStr + "001";
        }
        return commentCode;
    }


    private void checkCountAndSum(String tableName, String columnsName) {
        if (StringUtils.isBlank(tableName)) {
            throw new MyException("表名不能为空");
        }
        if (StringUtils.isBlank(columnsName)) {
            throw new MyException("列名不能为空");
        }
    }
    private void checkCountAndSum(String tableName) {
        if (StringUtils.isBlank(tableName)) {
            throw new MyException("表名不能为空");
        }
    }

}
